In this notebook we search for surgery diagrams of the branching sets of quotients of symmetric fillings of asymmetric L-space knots in A.
This is the complete list of the 49 hyperbolic symmetric slopes on knots in A.
symmetric_slopes=[['t12533', (-3, 1)],
['t12533', (-2, 1)],
['t12533', (-1, 1)],
['t12533', (0, 1)],
['t12533', (1, 1)],
['t12533', (-1, 2)],
['t12681', (-1, 1)],
['t12681', (1, 1)],
['t12681', (-1, 2)],
['t12681', (-2, 3)],
['t12681', (-1, 3)],
['o9_38928', (-2, 1)],
['o9_38928', (-1, 1)],
['o9_38928', (0, 1)],
['o9_38928', (1, 1)],
['o9_38928', (2, 1)],
['o9_39162', (-1, 1)],
['o9_39162', (1, 1)],
['o9_39162', (2, 1)],
['o9_39162', (1, 2)],
['o9_39162', (1, 4)],
['o9_40363', (-1, 1)],
['o9_40363', (1, 1)],
['o9_40363', (-1, 2)],
['o9_40363', (-1, 3)],
['o9_40363', (-3, 4)],
['o9_40487', (-2, 1)],
['o9_40487', (-1, 1)],
['o9_40487', (0, 1)],
['o9_40487', (1, 1)],
['o9_40487', (2, 1)],
['o9_40487', (3, 1)],
['o9_40487', (1, 2)],
['o9_40504', (-2, 1)],
['o9_40504', (-1, 1)],
['o9_40504', (0, 1)],
['o9_40504', (1, 1)],
['o9_40504', (2, 1)],
['o9_40582', (-1, 1)],
['o9_40582', (0, 1)],
['o9_40582', (1, 1)],
['o9_40582', (2, 1)],
['o9_40582', (4, 1)],
['o9_40582', (1, 2)],
['o9_42675', (-2, 1)],
['o9_42675', (-1, 1)],
['o9_42675', (0, 1)],
['o9_42675', (1, 1)],
['o9_42675', (2, 1)]]
We also need the list of slopes which have 3 different quotients. For those we want to find three different branching sets.
more_symmetries=[['t12681', (1, 1)], ['o9_38928', (2, 1)], ['o9_40363', (1, 1)], ['o9_40504', (2, 1)], ['o9_42675', (-2, 1)]]
In a first step we search for branching sets in the 3-sphere by going to the HT link table.
import time
import snappy
import pandas
DBChomologies = pandas.read_csv("DBChomologies_non_alternating.csv") # We load a list of all non alternating links in the HTLinkExteriors together with their homologies (if the homology is cyclic) and their crossing numbers.
### REMARK: To build the list we need to run the code in the file Build_DBChomologies which takes around 60 minutes. Here we just load it.
def double_branched_cover(link):
"""
Returns the double branched cover of the link.
"""
L=link.copy()
for i in range(L.num_cusps()):
L.dehn_fill((2,0),i)
for cov in L.covers(2):
if (2.0, 0.0) not in cov.cusp_info('filling'):
return cov
def better_is_isometric_to(X,Y,index):
"""
Returns True if X and Y are isometric.
Returns False if X and Y have different homologies. TO DO: Use volume to rigorously distinguish X and Y.
Returns 'unclear' if SnapPy cannot verify it.
The higher the index the harder SnapPy tries.
"""
w='unclear'
if X.homology()!=Y.homology():
w=False
if w=='unclear':
for i in (0,index):
try:
w=X.is_isometric_to(Y)
except RuntimeError:
pass
except snappy.SnapPeaFatalError:
pass
if w==True:
break
if w==False:
w='unclear'
X.randomize()
Y.randomize()
i=i+1
return w
def possible_DBC(homologies,max_crossings=15):
"""
Takes a list of orders of homologies and returns a list consisting of all DBC of alternating links in the HT link table with that homologies together with the link names.
"""
DBCList=[]
LINKS=[]
for order in homologies:
LINKS=LINKS+DBChomologies.loc[(DBChomologies['homology']==order) & (DBChomologies['crossings']<=max_crossings)]['knot'].tolist()
for link in LINKS:
L=snappy.Manifold(link)
D=double_branched_cover(L)
DBCList.append([D,link])
return DBCList
### The following two functions are written by Dunfield and search for positive triangulations.
def all_positive(manifold):
return manifold.solution_type() == 'all tetrahedra positively oriented'
def find_positive_triangulation(manifold, tries=100):
M = manifold.copy()
for i in range(tries):
if all_positive(M):
return M
M.randomize()
for d in M.dual_curves():
X = M.drill(d)
X = X.filled_triangulation()
X.dehn_fill((1,0))
for i in range(tries):
if all_positive(X):
return X
X.randomize()
# In the closed case, here is another trick.
if all(not c for c in M.cusp_info('is_complete')):
for i in range(tries):
# Drills out a random edge
X = M.__class__(M.filled_triangulation())
if all_positive(X):
return X
M.randomize()
def better_find_positive_triangulation(M,tries=1):
'''
Search for a positive triangulation, but ignores errors.
'''
RandomizeCount=0
while RandomizeCount<tries:
try:
X=find_positive_triangulation(M)
return X
except snappy.SnapPeaFatalError:
M.randomize()
RandomizeCount=RandomizeCount+1
return None
def is_alternating(knot,slope,try_hard=False,index=10,tries=1,max_cro=15):
'''
Checks if the slope is alternating.
'''
K=snappy.Manifold(knot)
K.dehn_fill(slope)
DBC=possible_DBC([K.homology().order()],max_crossings=max_cro)
for D in DBC:
w=better_is_isometric_to(D[0],K,index)
if w==True:
return [slope,D[1]]
if try_hard:
X=better_find_positive_triangulation(K,tries)
if X is not None:
for D in DBC:
Y=better_find_positive_triangulation(D[0],tries)
if Y is not None:
w=better_is_isometric_to(X,Y,index)
if w==True:
return [slope,D[1]]
return False
start_time = time.time()
branching_sets=[]
for (knot,slope) in symmetric_slopes:
w=is_alternating(knot,slope,index=25,max_cro=13)
if w!=False:
branching_sets.append([knot,w[0],w[1]])
print('We found a branching set:',knot,slope,w[1])
print('Total number of branching sets we have found:', len(branching_sets))
print('Total time taken: %s minutes ---' % ((time.time() - start_time)/60))
We found a branching set: t12533 (-1, 1) L12n789 We found a branching set: t12533 (0, 1) K12n407 We found a branching set: t12681 (-1, 1) L11n172 We found a branching set: o9_38928 (0, 1) L11n178 We found a branching set: o9_38928 (1, 1) K11n172 We found a branching set: o9_39162 (1, 1) L12n1050 We found a branching set: o9_40363 (-1, 1) L12n785 We found a branching set: o9_40487 (0, 1) L11n152 We found a branching set: o9_40487 (1, 1) K11n147 We found a branching set: o9_40504 (0, 1) L11n179 We found a branching set: o9_40504 (1, 1) K11n166 We found a branching set: o9_40582 (0, 1) L13n4413 We found a branching set: o9_40582 (1, 1) K13n2958 We found a branching set: o9_42675 (-1, 1) K12n730 We found a branching set: o9_42675 (0, 1) L12n702 Total number of branching sets we have found: 15 Total time taken: 1.4020240227381389 minutes ---
We get 15 branchings sets in the 3-sphere. It will turn out that together with the Seifert fibered alternating 3-sphere quotients these is the complete list of branching sets in the 3-sphere.
branching_sets
[['t12533', (-1, 1), 'L12n789'], ['t12533', (0, 1), 'K12n407'], ['t12681', (-1, 1), 'L11n172'], ['o9_38928', (0, 1), 'L11n178'], ['o9_38928', (1, 1), 'K11n172'], ['o9_39162', (1, 1), 'L12n1050'], ['o9_40363', (-1, 1), 'L12n785'], ['o9_40487', (0, 1), 'L11n152'], ['o9_40487', (1, 1), 'K11n147'], ['o9_40504', (0, 1), 'L11n179'], ['o9_40504', (1, 1), 'K11n166'], ['o9_40582', (0, 1), 'L13n4413'], ['o9_40582', (1, 1), 'K13n2958'], ['o9_42675', (-1, 1), 'K12n730'], ['o9_42675', (0, 1), 'L12n702']]
symmetric_slopes=[x for x in symmetric_slopes if x not in [[y[0],y[1]] for y in branching_sets]]
len(symmetric_slopes)
34
symmetric_slopes
[['t12533', (-3, 1)], ['t12533', (-2, 1)], ['t12533', (1, 1)], ['t12533', (-1, 2)], ['t12681', (1, 1)], ['t12681', (-1, 2)], ['t12681', (-2, 3)], ['t12681', (-1, 3)], ['o9_38928', (-2, 1)], ['o9_38928', (-1, 1)], ['o9_38928', (2, 1)], ['o9_39162', (-1, 1)], ['o9_39162', (2, 1)], ['o9_39162', (1, 2)], ['o9_39162', (1, 4)], ['o9_40363', (1, 1)], ['o9_40363', (-1, 2)], ['o9_40363', (-1, 3)], ['o9_40363', (-3, 4)], ['o9_40487', (-2, 1)], ['o9_40487', (-1, 1)], ['o9_40487', (2, 1)], ['o9_40487', (3, 1)], ['o9_40487', (1, 2)], ['o9_40504', (-2, 1)], ['o9_40504', (-1, 1)], ['o9_40504', (2, 1)], ['o9_40582', (-1, 1)], ['o9_40582', (2, 1)], ['o9_40582', (4, 1)], ['o9_40582', (1, 2)], ['o9_42675', (-2, 1)], ['o9_42675', (1, 1)], ['o9_42675', (2, 1)]]
Next we will search for branching sets in more general manifolds. For that we will take links in the HT link tables fill some one component of it to get a surgery diagram of a link in a manifold. Then we take the double branched cover of that link and search for a match with a symmetric filling on A.
DBChomologies_branching = pandas.read_csv("DBChomologies_one_filling.csv")
### REMARK: To build the list we need to run the code in the file Build_DBChomologies which takes around 3 days. Here we just load it.
def double_branched_cover(link):
"""
Returns the double branched covers of the link. This works also for links in a more general manifold.
Note that a knot in a more general manifold may have more than one double branched cover
(or no double branched cover at all if the knot represents a primitive element in homology).
This function will return the complete list of all double branched covers of the link.
"""
L=link.copy()
for i in range(L.num_cusps()):
if L.cusp_info(i).filling==(0.0, 0.0):
L.dehn_fill((2,0),i)
return [cov for cov in L.covers(2) if (2.0, 0.0) not in cov.cusp_info('filling')]
def possible_DBC_surgery_diagrams(homologies,max_crossings=15):
"""
Reads off the possible surgery diagrams.
"""
DBCList=[]
LINKS=[]
CUSPS=[]
SLOPES_STRINGS=[]
for order in homologies:
LINKS=LINKS+DBChomologies_branching.loc[(DBChomologies_branching['homology']==order) & (DBChomologies_branching['crossings']<=max_crossings)]['knot'].tolist()
CUSPS=CUSPS+DBChomologies_branching.loc[(DBChomologies_branching['homology']==order) & (DBChomologies_branching['crossings']<=max_crossings)]['cusp'].tolist()
SLOPES_STRINGS=SLOPES_STRINGS+DBChomologies_branching.loc[(DBChomologies_branching['homology']==order) & (DBChomologies_branching['crossings']<=max_crossings)]['filling'].tolist()
SLOPES=[]
for string in SLOPES_STRINGS:
string_without_brackets=string[1:-1]
SLOPES.append(tuple(map(int, string_without_brackets.split(', '))))
for i in range(0,len(LINKS)):
DBCList.append([LINKS[i],SLOPES[i],CUSPS[i]])
return DBCList
def search_for_branching_set(knot,slope,try_hard=False,index=10,tries=1,max_crossings=15):
'''
Searchs for a surgery diagram of the rbanching set
'''
K=snappy.Manifold(knot)
K.dehn_fill(slope)
DBC=possible_DBC_surgery_diagrams([K.homology().order()],max_crossings)
for DIAGRAM in DBC:
L=snappy.Manifold(DIAGRAM[0])
L.dehn_fill(DIAGRAM[1],DIAGRAM[2])
for D in double_branched_cover(L):
w=better_is_isometric_to(D,K,index)
if w==True:
return [[knot,slope,DIAGRAM[0],DIAGRAM[1],DIAGRAM[2]]]
if try_hard:
X=better_find_positive_triangulation(K,tries)
if X is not None:
for DIAGRAM in DBC:
L=snappy.Manifold(DIAGRAM[0])
L.dehn_fill(DIAGRAM[1],DIAGRAM[2])
for D in double_branched_cover(L):
Y=better_find_positive_triangulation(D,tries)
if Y is not None:
w=better_is_isometric_to(X,Y,index)
if w==True:
return [[knot,slope,DIAGRAM[0],DIAGRAM[1],DIAGRAM[2]]]
return False
def search_for_three_branching_sets(knot,slope,try_hard=False,index=10,tries=1,max_crossings=15):
'''
Searchs for a surgery diagram of the branching set
'''
BRANCHING_SETS=[]
K=snappy.Manifold(knot)
K.dehn_fill(slope)
homologies=[]
DBC=possible_DBC_surgery_diagrams([K.homology().order()],max_crossings)
for DIAGRAM in DBC:
L=snappy.Manifold(DIAGRAM[0])
L.dehn_fill(DIAGRAM[1],DIAGRAM[2])
for D in double_branched_cover(L):
w=better_is_isometric_to(D,K,index)
if w==True:
BRANCHING_SETS=BRANCHING_SETS+[[knot,slope,DIAGRAM[0],DIAGRAM[1],DIAGRAM[2]]]
for i in range(L.num_cusps()):
if L.cusp_info(i).filling==(0.0, 0.0):
L.dehn_fill((1,0),i)
if L.homology().order() not in homologies:
homologies.append(L.homology().order())
if len(homologies)==3:
return BRANCHING_SETS
if try_hard:
X=better_find_positive_triangulation(K,tries)
if X is not None:
for DIAGRAM in DBC:
L=snappy.Manifold(DIAGRAM[0])
L.dehn_fill(DIAGRAM[1],DIAGRAM[2])
for D in double_branched_cover(L):
Y=better_find_positive_triangulation(D,tries)
if Y is not None:
w=better_is_isometric_to(X,Y,index)
if w==True:
BRANCHING_SETS=BRANCHING_SETS+[[knot,slope,DIAGRAM[0],DIAGRAM[1],DIAGRAM[2]]]
for i in range(L.num_cusps()):
if L.cusp_info(i).filling==(0.0, 0.0):
L.dehn_fill((1,0),i)
if L.homology().order() not in homologies:
homologies.append(L.homology().order())
if len(homologies)==3:
return BRANCHING_SETS
return BRANCHING_SETS
start_time = time.time()
for (knot,slope) in symmetric_slopes:
if [knot,slope] in more_symmetries:
w=search_for_three_branching_sets(knot,slope,index=3,max_crossings=15)
if w==[]:
w=False
else:
w=search_for_branching_set(knot,slope,index=3,max_crossings=15)
if w!=False:
branching_sets=branching_sets+w
print('We found a branching set:',w)
print('Total number of branching sets we have found:', len(branching_sets))
print('Total time taken: %s minutes ---' % ((time.time() - start_time)/60))
We found a branching set: [['t12533', (-3, 1), 'L11n350', (-4, 1), 1]] We found a branching set: [['t12533', (-2, 1), 'L12n722', (3, 1), 0]] We found a branching set: [['t12533', (1, 1), 'L13n7360', (2, 1), 1]] We found a branching set: [['t12533', (-1, 2), 'L11n192', (-3, 1), 0]] We found a branching set: [['t12681', (1, 1), 'L11n419', (5, 1), 1], ['t12681', (1, 1), 'L12n1907', (3, 1), 1], ['t12681', (1, 1), 'L13n7356', (2, 1), 1]] We found a branching set: [['t12681', (-1, 2), 'L10a81', (3, 1), 0]] We found a branching set: [['t12681', (-2, 3), 'L13n4363', (-5, 3), 0]] We found a branching set: [['t12681', (-1, 3), 'L11a282', (-4, 1), 0]] We found a branching set: [['o9_38928', (-2, 1), 'L12n1949', (2, 1), 1]] We found a branching set: [['o9_38928', (-1, 1), 'L12n703', (3, 1), 0]] We found a branching set: [['o9_38928', (2, 1), 'L10a105', (-2, 1), 0], ['o9_38928', (2, 1), 'L10a105', (-2, 1), 1], ['o9_38928', (2, 1), 'L10n54', (-8, 1), 0], ['o9_38928', (2, 1), 'L10n54', (-8, 1), 1], ['o9_38928', (2, 1), 'L13n7433', (-3, 1), 1]] We found a branching set: [['o9_39162', (-1, 1), 'L13n9864', (-3, 1), 0]] We found a branching set: [['o9_39162', (2, 1), 'L10n44', (7, 1), 0]] We found a branching set: [['o9_39162', (1, 2), 'L12n784', (3, 1), 0]] We found a branching set: [['o9_39162', (1, 4), 'L13n4343', (-7, 4), 0]] We found a branching set: [['o9_40363', (1, 1), 'L11n419', (7, 1), 1], ['o9_40363', (1, 1), 'L13n9451', (3, 1), 1], ['o9_40363', (1, 1), 'L14n43377', (2, 1), 1]] We found a branching set: [['o9_40363', (-1, 2), 'L11a225', (-3, 1), 0]] We found a branching set: [['o9_40363', (-1, 3), 'L12a1861', (4, 1), 1]] We found a branching set: [['o9_40363', (-3, 4), 'L13n4363', (-7, 4), 0]] We found a branching set: [['o9_40487', (-2, 1), 'L12n1041', (-2, 1), 0]] We found a branching set: [['o9_40487', (-1, 1), 'L12n722', (-3, 1), 0]] We found a branching set: [['o9_40487', (2, 1), 'L11n333', (2, 1), 1]] We found a branching set: [['o9_40487', (3, 1), 'L12n1314', (7, 1), 0]] We found a branching set: [['o9_40487', (1, 2), 'L12n968', (-3, 1), 0]] We found a branching set: [['o9_40504', (-2, 1), 'L12n1037', (-2, 1), 0]] We found a branching set: [['o9_40504', (-1, 1), 'L12n715', (-3, 1), 0]] We found a branching set: [['o9_40504', (2, 1), 'L10a146', (-2, 1), 1], ['o9_40504', (2, 1), 'L10a146', (-2, 1), 2], ['o9_40504', (2, 1), 'L13n7421', (-3, 1), 1], ['o9_40504', (2, 1), 'L13n8521', (5, 1), 1]] We found a branching set: [['o9_40582', (-1, 1), 'L10n44', (-5, 3), 0]] We found a branching set: [['o9_40582', (2, 1), 'L13n9833', (3, 1), 0]] We found a branching set: [['o9_40582', (4, 1), 'L11n350', (-5, 1), 1]] We found a branching set: [['o9_40582', (1, 2), 'L12n996', (3, 1), 0]] We found a branching set: [['o9_42675', (-2, 1), 'L10n24', (6, 1), 1], ['o9_42675', (-2, 1), 'L11n223', (-2, 1), 0], ['o9_42675', (-2, 1), 'L13n5311', (2, 1), 0], ['o9_42675', (-2, 1), 'L13n9832', (8, 3), 1]] We found a branching set: [['o9_42675', (1, 1), 'L14n24428', (5, 3), 0]] We found a branching set: [['o9_42675', (2, 1), 'L13n7552', (-2, 1), 1]] Total number of branching sets we have found: 63 Total time taken: 86.03129815657934 minutes ---
branching_sets.sort()
branching_sets
[['o9_38928', (-2, 1), 'L12n1949', (2, 1), 1], ['o9_38928', (-1, 1), 'L12n703', (3, 1), 0], ['o9_38928', (0, 1), 'L11n178'], ['o9_38928', (1, 1), 'K11n172'], ['o9_38928', (2, 1), 'L10a105', (-2, 1), 0], ['o9_38928', (2, 1), 'L10a105', (-2, 1), 1], ['o9_38928', (2, 1), 'L10n54', (-8, 1), 0], ['o9_38928', (2, 1), 'L10n54', (-8, 1), 1], ['o9_38928', (2, 1), 'L13n7433', (-3, 1), 1], ['o9_39162', (-1, 1), 'L13n9864', (-3, 1), 0], ['o9_39162', (1, 1), 'L12n1050'], ['o9_39162', (1, 2), 'L12n784', (3, 1), 0], ['o9_39162', (1, 4), 'L13n4343', (-7, 4), 0], ['o9_39162', (2, 1), 'L10n44', (7, 1), 0], ['o9_40363', (-3, 4), 'L13n4363', (-7, 4), 0], ['o9_40363', (-1, 1), 'L12n785'], ['o9_40363', (-1, 2), 'L11a225', (-3, 1), 0], ['o9_40363', (-1, 3), 'L12a1861', (4, 1), 1], ['o9_40363', (1, 1), 'L11n419', (7, 1), 1], ['o9_40363', (1, 1), 'L13n9451', (3, 1), 1], ['o9_40363', (1, 1), 'L14n43377', (2, 1), 1], ['o9_40487', (-2, 1), 'L12n1041', (-2, 1), 0], ['o9_40487', (-1, 1), 'L12n722', (-3, 1), 0], ['o9_40487', (0, 1), 'L11n152'], ['o9_40487', (1, 1), 'K11n147'], ['o9_40487', (1, 2), 'L12n968', (-3, 1), 0], ['o9_40487', (2, 1), 'L11n333', (2, 1), 1], ['o9_40487', (3, 1), 'L12n1314', (7, 1), 0], ['o9_40504', (-2, 1), 'L12n1037', (-2, 1), 0], ['o9_40504', (-1, 1), 'L12n715', (-3, 1), 0], ['o9_40504', (0, 1), 'L11n179'], ['o9_40504', (1, 1), 'K11n166'], ['o9_40504', (2, 1), 'L10a146', (-2, 1), 1], ['o9_40504', (2, 1), 'L10a146', (-2, 1), 2], ['o9_40504', (2, 1), 'L13n7421', (-3, 1), 1], ['o9_40504', (2, 1), 'L13n8521', (5, 1), 1], ['o9_40582', (-1, 1), 'L10n44', (-5, 3), 0], ['o9_40582', (0, 1), 'L13n4413'], ['o9_40582', (1, 1), 'K13n2958'], ['o9_40582', (1, 2), 'L12n996', (3, 1), 0], ['o9_40582', (2, 1), 'L13n9833', (3, 1), 0], ['o9_40582', (4, 1), 'L11n350', (-5, 1), 1], ['o9_42675', (-2, 1), 'L10n24', (6, 1), 1], ['o9_42675', (-2, 1), 'L11n223', (-2, 1), 0], ['o9_42675', (-2, 1), 'L13n5311', (2, 1), 0], ['o9_42675', (-2, 1), 'L13n9832', (8, 3), 1], ['o9_42675', (-1, 1), 'K12n730'], ['o9_42675', (0, 1), 'L12n702'], ['o9_42675', (1, 1), 'L14n24428', (5, 3), 0], ['o9_42675', (2, 1), 'L13n7552', (-2, 1), 1], ['t12533', (-3, 1), 'L11n350', (-4, 1), 1], ['t12533', (-2, 1), 'L12n722', (3, 1), 0], ['t12533', (-1, 1), 'L12n789'], ['t12533', (-1, 2), 'L11n192', (-3, 1), 0], ['t12533', (0, 1), 'K12n407'], ['t12533', (1, 1), 'L13n7360', (2, 1), 1], ['t12681', (-2, 3), 'L13n4363', (-5, 3), 0], ['t12681', (-1, 1), 'L11n172'], ['t12681', (-1, 2), 'L10a81', (3, 1), 0], ['t12681', (-1, 3), 'L11a282', (-4, 1), 0], ['t12681', (1, 1), 'L11n419', (5, 1), 1], ['t12681', (1, 1), 'L12n1907', (3, 1), 1], ['t12681', (1, 1), 'L13n7356', (2, 1), 1]]
len(branching_sets)
63
Thus we have found all branching sets for all possible quotients of all symmetric fillings. Since non of these is an alternating knot in the 3-sphere this finishs the proof that no asymmetric L-space knot in the SnapPy census admits an alternating surgery.